﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SortableList.cs" company="TechBits">
//   Copyright (c) TechBits. All rights reserved.
// </copyright>
// <author>
//   Leandro G. Vacirca
// </author>
// <summary>
//   Defines the SortableList type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace IntelliShortCut.Helpers
{
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;

    /// <summary>
    /// Clase generica que implementa la funcionalidad para hacer una lista ordenable.
    /// </summary>
    /// <typeparam name="T">El tipo de datos contenidos en la lista.</typeparam>
    public class SortableList<T> : BindingList<T>
    {
        #region "Atributos Privados"

        /// <summary>
        /// Indica si la lista esta ordenada.
        /// </summary>
        private bool _isSorted;

        /// <summary>
        /// Indica la direccion de ordenamiento.
        /// </summary>
        private ListSortDirection _sortDirection;

        /// <summary>
        /// Sort descriptor de propiedad.
        /// </summary>
        private PropertyDescriptor _sortProperty;

        #endregion

        #region "Constructores"

        /// <summary>
        /// Initializes a new instance of the <see cref="SortableList&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="list">Lista que se requiere ordenable.</param>
        public SortableList(IList<T> list)
            : base(list)
        {
        }

        #endregion

        #region "Porpiedades Publicas"

        /// <summary>
        /// Gets a value indicating whether SupportsSortingCore.
        /// </summary>
        protected override bool SupportsSortingCore
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// Gets a value indicating whether IsSortedCore.
        /// </summary>
        protected override bool IsSortedCore
        {
            get
            {
                return _isSorted;
            }
        }

        /// <summary>
        /// Gets SortDirectionCore.
        /// </summary>
        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return _sortDirection;
            }
        }

        /// <summary>
        /// Gets SortPropertyCore.
        /// </summary>
        protected override PropertyDescriptor SortPropertyCore
        {
            get
            {
                return _sortProperty;
            }
        }

        #endregion

        #region "Metodos Publicos"

        /// <summary>
        /// Aplica el algoritmo de ordenamiento.
        /// </summary>
        /// <param name="prop">The property descriptor.</param>
        /// <param name="direction">The sort direction.</param>
        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            var d = direction == ListSortDirection.Ascending ? 1 : -1;
            ((List<T>)Items).Sort((x, y) => d * Comparer.Default.Compare(prop.GetValue(x), prop.GetValue(y)));
            _isSorted = true;
            _sortDirection = direction;
            _sortProperty = prop;
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

        /// <summary>
        /// Remueve el ordenamiento.
        /// </summary>
        protected override void RemoveSortCore()
        {
            _isSorted = false;
        }

        #endregion
    }
}